package cn.dlc.com.filter;

import cn.dlc.com.config.RsaPropertiesConfig;
import cn.dlc.com.pojo.SysRole;
import cn.dlc.com.pojo.SysUser;
import cn.dlc.com.utils.JsonUtils;
import cn.dlc.com.utils.JwtUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.xml.internal.ws.resources.HttpserverMessages;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author deng
 * @date 2021/6/25 10:53
 **/
public class JwtLoginFilter extends UsernamePasswordAuthenticationFilter {

    private AuthenticationManager authenticationManager;
    private RsaPropertiesConfig config;


    public JwtLoginFilter(AuthenticationManager authenticationManager, RsaPropertiesConfig config) {
        this.authenticationManager = authenticationManager;
        this.config = config;
    }

    // 重写登录认证的方法
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        ObjectMapper objectMapper = new ObjectMapper();

        try {
            // 获取到用户信息
            SysUser sysUser = objectMapper.readValue(request.getInputStream(), SysUser.class);
            if(sysUser == null) {
                // 认证失败
                return null;
            }
            // 进行认证
            UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(
                    sysUser.getUsername(), sysUser.getPassword());
            // 认证成功
            return authenticationManager.authenticate(authRequest);

        } catch (Exception e) {
            e.printStackTrace();
            authFail(response);
            // 这一句要写么？
            throw new RuntimeException();
        }
    }

    // 认证通过之后的操作
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
                                            FilterChain chain, Authentication authResult) throws IOException, ServletException {
        if(authResult != null) {
            SysUser sysUser = new SysUser();
            sysUser.setUsername(authResult.getName());
            sysUser.setRoles((List<SysRole>) authResult.getAuthorities());
            // 生成对应的token(默认一分钟过期)
            String token = JwtUtils.generateTokenExpireInSeconds(sysUser, config.getPrivateKey(), 1 * 60);
            // 响应给页面，以头的方式
            response.addHeader("Authorization","Bearer " + token);
            // 认证通过
            authSuccess(response);

        } else {
            authFail(response);
            // 没有权限，
            throw new RuntimeException();
        }
    }

    // 认证失败
    private void authFail(HttpServletResponse response){
        try {
            response.setContentType("application/json");
            // 认证失败
            response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            PrintWriter writer = response.getWriter();

            Map<String,Object> map = new HashMap<>();
            map.put("code",HttpServletResponse.SC_UNAUTHORIZED);
            map.put("msg","用户名或者密码错误");
            writer.write(JsonUtils.toString(map));
            writer.flush();
            writer.close();

        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }

    // 认证通过
    private void authSuccess(HttpServletResponse response){
        try {
            response.setContentType("application/json");
            response.setStatus(HttpServletResponse.SC_OK);
            PrintWriter writer = response.getWriter();

            Map<String,Object> map = new HashMap<>();
            map.put("code",HttpServletResponse.SC_OK);
            map.put("msg","认证通过！");
            writer.write(JsonUtils.toString(map));
            writer.flush();
            writer.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
